﻿using System;
using System.Linq;
using System.Threading;
using Equinoxe.EZNFC.ACR122.Library;
using Equinoxe.EZNFC.Library;
using Equinoxe.EZNFC.Library.Tags;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Equinoxe.EZNFC.UnitTests
{
    [TestClass, System.Runtime.InteropServices.GuidAttribute("EB4C36B5-361C-4753-90BF-C0CD130A70DD")]
    public class UnitTest1
    {
        private Ports _goodPort = Ports.COM3;
        private Ports _badPort = Ports.COM9;

        #region Device basic tests

        /// <summary>
        /// Tests opening the device ANSI mode.
        /// </summary>
        /// <remarks></remarks>
        [TestMethod]
        public void OpenDeviceAnsi()
        {
            using (
                var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort,
                                                       ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                device.Close();
            }

        }

        /// <summary>
        ///Tests opening the device unicode mode.
        /// </summary>
        /// <remarks></remarks>
        [TestMethod]
        public void OpenDeviceUnicode()
        {


            using (
                var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort,
                                                       ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {

                Assert.IsNotNull(device);

                device.Open();

                device.Close();
            }

        }

        /// <summary>
        /// Tests opening device wrong port.
        /// </summary>
        /// <remarks></remarks>
        [TestMethod]
        public void OpenDeviceFail()
        {

            using (
                var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _badPort,
                                                       ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

            }

        }

        /// <summary>
        /// Test settings bauds.
        /// </summary>
        /// <remarks></remarks>
        [TestMethod]
        public void SetBauds()
        {

            using (
                var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort,
                                                       ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                device.SetBaudRate(ACR122Device.DeviceInfoStatic.BaudsAvailable.Skip(1).FirstOrDefault());

                device.Close();
            }

        }


        /// <summary>
        /// Tests getting the slots.
        /// </summary>
        /// <remarks></remarks>
        [TestMethod]
        public void GetSlots()
        {


            using (
                var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort,
                                                       ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                int numberOfSlots;

                device.GetNumberOfSlots(out numberOfSlots);

                Assert.AreEqual(3, numberOfSlots);

                device.Close();

            }

        }


        /// <summary>
        /// Tests get the timeouts.
        /// </summary>
        /// <remarks></remarks>
        [TestMethod]
        public void GetTimeOuts()
        {

            using (
                var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort,
                                                       ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                var timeouts = device.GetTimeouts();

                device.Close();
            }

        }

        /// <summary>
        /// Tests set the timeouts.
        /// </summary>
        /// <remarks></remarks>
        [TestMethod]
        public void SetTimeOuts()
        {




            using (
                var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort,
                                                       ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                var timeouts = new ACR122Timeouts
                                   {
                                       NumberOfResponseRetry = 2,
                                       NumberOfStatusRetry = 3,
                                       ResponseTimeout = 10,
                                       StatusTimeout = 20
                                   };

                device.SetTimeouts(timeouts);

                var timeouts2 = device.GetTimeouts();

                Assert.AreEqual(timeouts.NumberOfResponseRetry, timeouts2.NumberOfResponseRetry);
                Assert.AreEqual(timeouts.NumberOfStatusRetry, timeouts2.NumberOfStatusRetry);
                Assert.AreEqual(timeouts.ResponseTimeout, timeouts2.ResponseTimeout);
                Assert.AreEqual(timeouts.StatusTimeout, timeouts2.StatusTimeout);

                device.Close();

            }

        }

        [TestMethod]
        public void TestGetFirmware()
        {
            using (
                var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort,
                                                       ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                var firmware = device.GetFirmware();

                Assert.AreNotEqual(string.Empty, firmware);

                device.Close();
            }
        }

        #endregion


        #region LCD Tests

        [TestMethod]
        public void TestShowLCDMessage()
        {
            using (
                var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort,
                                                       ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();
                // Try Display less than 16 char
                device.DisplayLCDMessage("Hello world !");

                device.ClearLCD();

                device.Close();
            }
        }

        public void TestShowLongLCDMessage()
        {
            using (
                var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort,
                                                       ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                // Try Display more than 16 char
                device.DisplayLCDMessage("Hello world !Hello world !");

                device.ClearLCD();

                device.Close();
            }
        }

        [TestMethod]
        public void TestShowBoldLCDMessage()
        {
            using (
                var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort,
                                                       ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                // Try Display less than 16 char
                device.DisplayLCDMessageEx("Hello world !", 1, 0);

                device.ClearLCD();

                device.Close();
            }
        }

        [TestMethod]
        public void TestShowChineseBoldLCDMessage()
        {
            using (
                var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort,
                                                       ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                // Try Display less than 16 char
                device.DisplayLCDMessageChinese("你好", 1);

                device.ClearLCD();

                device.Close();

            }
        }

        [TestMethod]
        public void TestShowLongChineseBoldLCDMessage()
        {
            using (
                var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort,
                                                       ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                // Try Display less than 16 char
                device.DisplayLCDMessageChinese("你好你好你好你好你好你好你好你好你好你好你好你好", 1);

                device.ClearLCD();

                device.Close();
            }
        }


        [TestMethod]
        public void TestScrollLCD()
        {
            using (
                var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort,
                                                       ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                // Try Display less than 16 char
                device.DisplayLCDMessage("Hello world !");

                device.StartLCDScrolling(125, LCDScrollDirection.LeftToRight);

                device.LCDPauseScroll();

                device.LCDStopScroll();

                device.ClearLCD();

                device.Close();
            }
        }

        [TestMethod]
        public void TestLCDBackLight()
        {
            using (
                var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort,
                                                       ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                // Try Display less than 16 char
                device.EnableLCDBackLight();

                device.LCDContrast(15);

                device.DisableLCDBackLight();

                device.Close();

            }
        }

        [TestMethod]
        public void TestLCDDrawLine()
        {
            using (
                var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort,
                                                       ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                var buffer = new byte[]
                                 {
                                     0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22,
                                     0x11, 0x00
                                 };

                //var buffer2 = new byte[16]
                //                 {
                //                     0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                //                     0x00, 0x00
                //                 };

                // Try Display less than 16 char
                device.DrawLCDLine(buffer, buffer.Length);

                device.ClearLCD();

                device.Close();
            }
        }

        [TestMethod]
        public void TestLCDDraw()
        {
            using (
                var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort,
                                                       ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                device.DrawLCDImage(@"d:\test.jpg");

                //device.ClearLCD();

                device.Close();
            }
        }

        #endregion


        #region LED Tests

        [TestMethod]
        public void TestEnableLED()
        {
            using (var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort, ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                device.EnableLED();

                device.Close();

            }
        }

        [TestMethod]
        public void TestDisableLED()
        {
            using (var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort, ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                device.DisableLED();

                device.Close();
            }
        }

        [TestMethod]
        public void TestSetLED()
        {
            using (var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort, ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                device.SetLED(0, true);
                device.SetLED(1, true);
                device.SetLED(2, true);
                device.SetLED(3, true);

                device.Close();

            }
        }

        [TestMethod]
        public void TestSetLEDAndBeep()
        {
            using (var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort, ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                device.SetLEDAndBeep(true, true, true, 250, 250, 5, BuzzerMode.Off);

                device.Close();

            }
        }

        #endregion

        #region Buzzer
        [TestMethod]

        public void TestBeep()
        {
            using (var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort, ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                device.Buzzer(100, 100, 5);

                device.Close();
            }
        }
        #endregion

        #region Tag
        [TestMethod]
        public void Poll()
        {
            using (var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort, ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                var timeouts = new ACR122Timeouts
                {
                    NumberOfResponseRetry = 2,
                    NumberOfStatusRetry = 3,
                    ResponseTimeout = 2,
                    StatusTimeout = 4
                };

                device.SetTimeouts(timeouts);

                var tag = device.Poll();

                Assert.IsInstanceOfType(tag, typeof(Mifare1K));

                device.Close();
            }
        }

        [TestMethod]
        public void Polling()
        {
            using (var device = ACR122Device.CreateDevice(DeviceCharset.Ansi, _goodPort, ACR122Device.DeviceInfoStatic.BaudsAvailable.FirstOrDefault()))
            {
                Assert.IsNotNull(device);

                device.Open();

                var timeouts = new ACR122Timeouts
                                   {
                                       NumberOfResponseRetry = 2,
                                       NumberOfStatusRetry = 3,
                                       ResponseTimeout = 2,
                                       StatusTimeout = 4
                                   };

                device.SetTimeouts(timeouts);

                device.TagDetected += (o, t) =>
                                          {
                                              Assert.IsInstanceOfType(t.NFCTag, typeof(Mifare1K));
                                              Console.WriteLine("Tag detected");
                                          };


                device.StartPolling();

                Thread.Sleep(1000);

                device.StopPolling();

                device.Close();

            }
        }

        #endregion


    }
}
